package manager

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"

	"gitee.com/zh-jn/harmonica-previewer-online/api"
)

type PreviewerDescriptor struct {
	PreviewerId string `json:"previewer_id"`
	Namespace   string `json:"namespace"`
}

type AllocatePreviewerReq struct {
	SessionId string `json:"session_id"`
}

type ReleasePreviewerReq struct {
	AllocatePreviewerReq `json:",inline"`
	PreviewerId          string `json:"previewer_id"`
}

type CheckBindingReq = ReleasePreviewerReq

func RunServer(cfg Config) {
	mgr := NewPreviewerManager(cfg)
	if err := mgr.Init(); err != nil {
		panic(err)
	}
	mux := http.NewServeMux()
	mux.HandleFunc("/allocate_previewer", GetAllocatePreviewerHandler(mgr))
	mux.HandleFunc("/release_previewer", GetReleasePreviewerHandler(mgr))
	mux.HandleFunc("/check_binding", CheckBinding(mgr))
	if err := http.ListenAndServe(fmt.Sprintf("%v:%v", cfg.Addr, cfg.Port), mux); err != nil {
		panic(err)
	}
}

func CheckBinding(mgr *PreviewerManager) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		reqbody, err := ioutil.ReadAll(r.Body)
		if err != nil {
			w.WriteHeader(http.StatusOK)
			w.Write(api.RspBuf(nil, err))
			return
		}
		var req CheckBindingReq
		if err = json.Unmarshal(reqbody, &req); err != nil {
			w.WriteHeader(http.StatusOK)
			w.Write(api.RspBuf(nil, err))
			return
		}

		err = mgr.CheckBinding(req.SessionId, req.PreviewerId)
		if err != nil {
			w.WriteHeader(http.StatusOK)
			w.Write(api.RspBuf(nil, err))
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Write(api.RspBuf(nil, nil))
		return
	}
}

func GetAllocatePreviewerHandler(mgr *PreviewerManager) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		reqbody, err := ioutil.ReadAll(r.Body)
		if err != nil {
			w.WriteHeader(http.StatusOK)
			w.Write(api.RspBuf(nil, err))
			return
		}
		var req AllocatePreviewerReq
		if err = json.Unmarshal(reqbody, &req); err != nil {
			w.WriteHeader(http.StatusOK)
			w.Write(api.RspBuf(nil, err))
			return
		}
		prevD, err := mgr.AllocatePreviewer(req.SessionId)
		if err != nil {
			w.WriteHeader(http.StatusOK)
			w.Write(api.RspBuf(nil, err))
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Write(api.RspBuf(prevD, nil))
		return
	}
}

func GetReleasePreviewerHandler(mgr *PreviewerManager) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		reqbody, err := ioutil.ReadAll(r.Body)
		if err != nil {
			w.WriteHeader(http.StatusOK)
			w.Write(api.RspBuf(nil, err))
			return
		}
		var req ReleasePreviewerReq
		if err = json.Unmarshal(reqbody, &req); err != nil {
			w.WriteHeader(http.StatusOK)
			w.Write(api.RspBuf(nil, err))
			return
		}
		err = mgr.ReleasePreviewer(req.SessionId, req.PreviewerId)
		if err != nil {
			w.WriteHeader(http.StatusOK)
			w.Write(api.RspBuf(nil, err))
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Write(api.RspBuf(nil, nil))
		return
	}
}
